using System;
using System.Collections;
using System.Web.UI;
using PHSRAG.Insight21.CDS;
using PHSRAG.Insight21.Common.Pages;
using PHSRAG.Insight21.FormsManagement;
using PHSRAG.Insight21.Policy;
using PHSRAG.Insight21.ScriptEngine;
using PHSRAG.Utility;
using Forms = PHSRAG.Insight21.FormsManagement;
using ScriptReference=PHSRAG.Insight21.ScriptEngine.ScriptReference;

namespace PHSRAG.Insight21.Humans
{
    /// <summary>
    /// This page hosts the Questionnaire viewer control to let the user to alter or add the answers for the Questionnaire. 
    /// The questionnaire viewer control loads the questionnaire based on the Questionnaire Version.
    /// </summary>
    public partial class AnswerEditor : BasePage
    {
        private const string PageCacheKey = "answerQuestionnairePage__C9AD7E48-EF5C-4267-871C-A941705DEB8C";
        private const string ProtocolIdKey = "ProtocolId_4E7DDF5C-6EEA-483b-895E-2ABA7B805EE4";
        private const string ProtocolProcessIdKey = "PPId_842BB447-BD65-477c-81CD-5587922FCC17";

        #region Instance Variables(private)

        private ICachePolicy applicationCachePolicy;
        private ICachePolicy cachePolicy;
        private Hashtable pageCache;
        private ICachePolicy pageCachePolicy;
        private Protocol protocol;
        private int protocolId;
        private ProtocolProcess protocolProcess;
        private int protocolProcessId;

        #endregion

        #region Private properties

        /// <summary>
        /// Gets the protocol for which staffing is being reviewed or modified.  If it's not already
        /// in the cache, it loads it up based on the protocolId passed to the page, and caches the object
        /// </summary>
        private Protocol Protocol
        {
            get
            {
                string cacheKey = Protocol.ProtocolKey;
                protocol = cachePolicy.GetCachedObject(cacheKey) as Protocol;

                if ((protocol == null) || (protocolId != protocol.Id))
                {
                    protocol = new Protocol(cachePolicy);
                    protocol.Load(DataAccess.GetConnectionString(), protocolId);
                    cachePolicy.Cache(cacheKey, protocol);
                }
                return protocol;
            }
        }


        /// <summary>
        /// Gets the protocol process . If it's not already
        /// in the cache, it loads it up based on the protocolProcessId passed to the page, and caches the 
        /// object
        /// </summary>
        private ProtocolProcess ProtocolProcess
        {
            get
            {
                protocolProcess =
                    cachePolicy.GetCachedObject(ProtocolProcess.ProtocolProcessKey) as ProtocolProcess;

                if ((protocolProcess == null) || (protocolProcessId != protocolProcess.Id))
                {
                    if (0 == protocolProcessId)
                    {
                        protocolProcess = null;
                    }
                    else
                    {
                        protocolProcess = ProtocolProcess.GetProtocolProcess(
                            DataAccess.GetConnectionString(), protocolProcessId, cachePolicy, null);
                        cachePolicy.Cache(ProtocolProcess.ProtocolProcessKey, protocolProcess);
                    }
                }

                if (null == protocolProcess)
                {
                    throw new Exception("No protocol process available.");
                }

                return protocolProcess;
            }
        }

        #endregion

        /// <summary>
        /// PageLoad event to display the Questionnaire for edition
        /// </summary>
        /// <param name="sender">sender of the event</param>
        /// <param name="e">event arguments</param>
        protected void OnPageLoad(object sender, EventArgs e)
        {
            try
            {
                pageCache = pageCachePolicy.GetCachedObject(PageCacheKey) as Hashtable ?? new Hashtable();
                if (!IsPostBack && postbackGuard.IsValid)
                {
                    Hashtable incomingPageHash =
                        cachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;
                    if (incomingPageHash != null)
                    {
                        protocolId = Convert.ToInt32(incomingPageHash[Keys.ProtocolIdKey]);
                        pageCache[ProtocolIdKey] = protocolId;
                        protocolProcessId = Convert.ToInt32(incomingPageHash[Keys.ProtocolProcessIdKey]);
                        pageCache[ProtocolProcessIdKey] = protocolProcessId;
                        pageCachePolicy.Cache(PageCacheKey, pageCache);
                    }
                    else
                    {
                        protocolId = (int) pageCache[ProtocolIdKey];
                        protocolProcessId = (int) pageCache[ProtocolProcessIdKey];
                    }
                    LoadUserControlForEditingAnswers();
                }
                else
                {
                    protocolId = (int) pageCache[ProtocolIdKey];
                    protocolProcessId = (int) pageCache[ProtocolProcessIdKey];
                }
            }
            catch (Exception ex)
            {
                annunciator.Title = InsightUtilities.Constants.Annunciator.Title;
                annunciator.Message = ex.Message;
            }
        }

        /// <summary>
        /// Load the Questionnaire viewer with the questionnaire items corresponding to the version of the Questionnaire.
        /// </summary>
        private void LoadUserControlForEditingAnswers()
        {
            try
            {
                QuestionnaireAnswer questionnaireAnswer = new QuestionnaireAnswer(cachePolicy);
                QuestionnaireVersion questionnaireVersion = new QuestionnaireVersion(cachePolicy);
                questionnaireAnswer = cachePolicy.GetCachedObject(questionnaireAnswer.CacheKey()) as QuestionnaireAnswer;
                questionnaireVersion = cachePolicy.GetCachedObject(questionnaireVersion.CacheKey()) as QuestionnaireVersion;

                //name of the questionnaire
                questionaireTitle.Text = questionnaireVersion.Questionnaire.Name;

                // set these on the Control
                if (questionnaireVersion.Questionnaire.AllowMultiple)
                {
                    questionnaireViewer.QuestionnaireAnswerName = questionnaireAnswer.Name;
                }

                if (questionnaireAnswer != null)
                {
                    questionnaireViewer.LoadQuestionnaire(questionnaireVersion, questionnaireAnswer);
                }
                else
                {
                    throw new Exception("Failed to load the questionnaire , Questionnaire version does not exist");
                }
            }
            catch (Exception ex)
            {
                annunciator.Title = InsightUtilities.Constants.Annunciator.Title;
                annunciator.Message = ex.Message;
            }
        }

        /// <summary>
        /// Event to save the answers edited/added by the logged in user
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnSave(object sender, ImageClickEventArgs e)
        {
            try
            {
                QuestionnaireAnswer questionnaireAnswer = new QuestionnaireAnswer(cachePolicy);
                questionnaireAnswer = cachePolicy.GetCachedObject(questionnaireAnswer.CacheKey()) as QuestionnaireAnswer;
                if (!questionnaireViewer.VerifyTextboxAnswers())
                {
                    return;
                }
                questionnaireViewer.SaveQuestionnaire(questionnaireAnswer);
                questionnaireAnswer.Save(DataAccess.GetConnectionString());

                ProtocolVersion protocolVersion = ProtocolProcess.GetLatestProtocolVersion(true, cachePolicy);

                ProtocolProcess.VerifyRequiredAttachments(questionnaireAnswer, ((RefCodes) applicationCachePolicy.GetCachedObject(RefCodes.CacheKey)), protocolVersion);

                ProtocolProcess.LastModifiedDate = DateTime.Now;
                ProtocolProcess.Save(DataAccess.GetConnectionString());

                // Run the requirement script for the appropriate QuestionnaireVersion here.
                QuestionnaireVersion version = questionnaireAnswer.QuestionnaireVersion;

                Script requirementScript =
                    (Script) version.Scripts[FormsManagement.Constants.ScriptType.Requirement];

                if (requirementScript != null)
                {
                    using (ScriptEngineHost scriptHost =
                        new ScriptEngineHost(
                            string.Format("{0}{1}", version.Id,
                                ScriptEngine.Constants.RootMoniker.RequirementScriptMoniker),
                            ScriptEngine.Constants.RootNamespaces.RequirementScript,
                            true))
                    {
                        ArrayList refs = ScriptReference.GetAllScriptReferences(
                            DataAccess.GetConnectionString());

                        for (int i = 0; i < refs.Count; ++i)
                        {
                            ScriptReference reference = (ScriptReference) refs[i];
                            scriptHost.AddDLLReference(reference.Path);
                        }

                        Protocol theProtocol = new Protocol(cachePolicy);
                        theProtocol.Load(DataAccess.GetConnectionString(), protocolId);

                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.ProtocolProcss, ProtocolProcess);

                        // add this protocol as an intrinsic.
                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.Protocol, theProtocol);

                        // add the connection string
                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.ConnectionString,
                            DataAccess.GetConnectionString());

                        // add the QuestionnaireAnswer
                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.QuestionnaireAnswer,
                            questionnaireAnswer);

                        // add the version
                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.ProtocolVersion, protocolVersion);

                        // add the caching policy
                        scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.CachePolicy, cachePolicy);

                        // compile and run the script.
                        if (scriptHost.Compile(requirementScript))
                        {
                            scriptHost.RunScript(requirementScript,
                                ScriptEngine.Constants.AssemblyType.RequirementScript,
                                ScriptEngine.Constants.MethodsToRun.Main);
                        }
                    }
                }

                // close the popup 
                Page.ClientScript.RegisterClientScriptBlock(GetType(), "LogItem", "<script language='javascript'>window.close();</script>");
            }
            catch (Exception ex)
            {
                annunciator.Title = InsightUtilities.Constants.Annunciator.Title;
                annunciator.Message = ex.Message;
            }
        }

        /// <summary>
        /// Event to close the questionnaire without saving the changes
        /// </summary>
        /// <param name="sender">Close button</param>
        /// <param name="e">click event args</param>
        private void OnCancel(object sender, ImageClickEventArgs e)
        {
            // close the popup 
            Page.ClientScript.RegisterClientScriptBlock(GetType(), "LogItem", "<script language='javascript'>window.close();</script>");
        }

        #region Web Form Designer generated code

        /// <summary>
        /// Initialization event
        /// </summary>
        /// <param name="e"></param>
        protected override void OnInit(EventArgs e)
        {
            //
            // CODEGEN: This call is required by the ASP.NET Web Form Designer.
            //
            InitializeComponent();
            base.OnInit(e);
            cachePolicy = (Policy.ICachePolicy) Session[Policy.Names.CachePolicyKey];
            pageCachePolicy = (Policy.ICachePolicy) Session[Policy.Names.PageCachePolicyKey];
            applicationCachePolicy = (Policy.ICachePolicy) Application[Policy.Names.ApplicationCachePolicyKey];
        }

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.cancel.Click += new ImageClickEventHandler(OnCancel);
            this.Save.Click += new ImageClickEventHandler(OnSave);
            this.Load += new System.EventHandler(this.OnPageLoad);
        }

        #endregion
    }
}